/// <reference types="node" />
import { io, Socket } from 'socket.io-client';
import type { GpsLogData } from '@/types/track';
import { logger } from './logger';
import { ENV } from '@/config/env';

class WebSocketService {
  private socket: Socket | null = null;
  private listeners: Map<string, Set<Function>> = new Map();
  private connectionAttempts: number = 0;
  private readonly MAX_RETRY_COUNT = 5;
  private readonly RETRY_INTERVAL = 3000;
  private retryTimeout: NodeJS.Timeout | null = null;
  private isInitialized = false;

  constructor() {
    // 延迟初始化，等待环境准备就绪
    setTimeout(() => {
      if (!this.isInitialized) {
        this.initialize();
      }
    }, 100);
  }

  private initialize() {
    if (this.isInitialized) return;
    this.isInitialized = true;
    this.connect();
  }

  private async connect() {
    if (this.socket?.connected) {
      logger.debug('Socket already connected, skipping connection', 'WebSocketService');
      return;
    }

    this.cleanup();

    try {
      const { data: token } = await uni.getStorage({ key: 'auth_token' });
      if (!token) throw new Error('未授权');
      
      // 使用统一的logger输出调试信息
      logger.debug('WebSocket连接配置信息', 'WebSocketService', {
        wsUrl: ENV.WS_URL,
        environment: import.meta.env.MODE,
        pageUrl: window.location.href
      });
      
      // 输出连接地址以便调试
      logger.debug('正在连接WebSocket服务器', 'WebSocketService', {
        url: ENV.WS_URL,
        token: '***' // 隐藏实际token
      });

      this.socket = io(ENV.WS_URL, {
        auth: { token },
        transports: ['websocket'],  // 只使用 websocket
        upgrade: true,
        // 添加重连配置
        reconnection: true,
        reconnectionAttempts: 5,
        reconnectionDelay: 3000,
        timeout: 20000,
        // Socket.IO 配置
        path: '/socket.io/',
      });

      if (!this.socket) {
        throw new Error('Failed to create socket instance');
      }

      // 使用安全的事件监听方式
      this.socket?.on('connect', this.handleConnect.bind(this));
      this.socket?.on('connect_error', this.handleConnectError.bind(this));
      this.socket?.on('reconnect_attempt', this.handleReconnectAttempt.bind(this));

      // 绑定事件监听
      this.bindEvents();

      // 手动连接
      this.socket.connect();

    } catch (error) {
      logger.error('连接失败', error instanceof Error ? error.message : String(error));
      this.handleConnectionError();
    }
  }

  private bindEvents() {
    if (!this.socket) return;

    const socket = this.socket;

    // 移除所有现有的监听器
    socket.removeAllListeners();

    // 基础连接事件
    socket.on('connect', () => {
      logger.debug('Socket connected successfully', 'WebSocketService');
      this.connectionAttempts = 0;
    });

    socket.on('disconnect', (reason: string) => {
      logger.warn('Socket disconnected', 'WebSocketService', { reason });
      if (reason === 'io server disconnect' || reason === 'transport close') {
        this.handleDisconnect(reason);
      }
    });

    // 错误处理
    socket.on('connect_error', (error: Error) => {
      logger.error('Socket connection error', 'WebSocketService', { 
        error: error.message 
      });
      this.handleConnectionError();
    });

    socket.on('error', (error: Error) => {
      logger.error('Socket error', 'WebSocketService', { 
        error: error.message 
      });
    });

    // 业务事件
    socket.on('gps_update', (data: GpsLogData) => {
      try {
        logger.debug('Received GPS update', 'WebSocketService', {
          deviceId: data.deviceId,
          timestamp: data.timestamp
        });
        this.notifyListeners('gps_update', data);
      } catch (error) {
        logger.error('Error handling GPS update', 'WebSocketService', {
          error: error instanceof Error ? error.message : String(error)
        });
      }
    });

    // 重新绑定所有注册的监听器
    this.listeners.forEach((callbacks, event) => {
      callbacks.forEach(callback => {
        socket.on(event, callback as (...args: any[]) => void);
      });
    });
  }

  private cleanup() {
    if (this.socket) {
      try {
        this.socket.removeAllListeners();
        this.socket.disconnect();
      } catch (e) {
        logger.warn('Error while cleaning up socket', 'WebSocketService', { 
          error: e instanceof Error ? e.message : String(e) 
        });
      }
      this.socket = null;
    }

    if (this.retryTimeout) {
      clearTimeout(this.retryTimeout);
      this.retryTimeout = null;
    }
  }

  private handleConnectionError() {
    this.connectionAttempts++;
    if (this.connectionAttempts < this.MAX_RETRY_COUNT) {
      logger.debug('Scheduling reconnection attempt', 'WebSocketService', {
        attempt: this.connectionAttempts,
        maxAttempts: this.MAX_RETRY_COUNT
      });

      this.retryTimeout = setTimeout(() => {
        logger.debug('Attempting to reconnect', 'WebSocketService', {
          attempt: this.connectionAttempts + 1,
          maxAttempts: this.MAX_RETRY_COUNT
        });
        this.connect();
      }, this.RETRY_INTERVAL);
    } else {
      logger.error('Max reconnection attempts reached', 'WebSocketService', {
        attempts: this.connectionAttempts
      });
    }
  }

  private handleDisconnect(reason: string) {
    logger.debug('Handling disconnect', 'WebSocketService', { reason });
    if (this.connectionAttempts < this.MAX_RETRY_COUNT) {
      setTimeout(() => {
        this.connect();
      }, 1000);
    }
  }

  public on(event: string, callback: (data: any) => void) {
    if (this.socket) {
      this.socket.on(event, (data) => {
        try {
          callback(data);
        } catch (error) {
          logger.error('事件处理错误', 'SocketService', {
            event,
            error: error instanceof Error ? error.message : String(error)
          });
        }
      });
    }
  }

  public off(event: string, callback: Function) {
    this.listeners.get(event)?.delete(callback);
    if (this.socket) {
      this.socket.off(event, callback as (...args: any[]) => void);
    }
  }

  private notifyListeners(event: string, data: any) {
    this.listeners.get(event)?.forEach(callback => {
      try {
        callback(data);
      } catch (error) {
        logger.error('Error in event listener', 'WebSocketService', {
          event,
          error: error instanceof Error ? error.message : String(error)
        });
      }
    });
  }

  public isConnected(): boolean {
    return this.socket?.connected ?? false;
  }

  public reconnect() {
    this.connectionAttempts = 0;
    this.connect();
  }

  public disconnect() {
    this.cleanup();
  }

  private handleConnect() {
    logger.debug('Socket连接成功');
  }

  private handleConnectError(error: Error) {
    logger.error('连接错误', error.message);
  }

  private handleReconnectAttempt(attempt: number) {
    logger.debug(`第${attempt}次重试连接`);
  }
}

async function getToken() {
  try {
    const { data: token } = await uni.getStorage({ key: 'auth_token' });
    return token;
  } catch (error) {
    console.error('Token获取失败:', error);
    return '';
  }
}

// 创建单例实例
export const wsService = new WebSocketService();
export default wsService; 